package com.shoulder.core.utils;


import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class MapUtils {


    /**
     * @param e            key
     * @param map          map对象
     * @param defaultValue 默认值
     * @param <E>          key
     * @param <T>          value
     * @return value
     */
    public static <E, T> T get(E e, Map<E, T> map, T defaultValue) {
        if (e == null || !map.containsKey(e)) {
            return defaultValue;
        }
        return map.get(e);
    }

    /**
     * @param e   key
     * @param map map对象
     * @param <E> key
     * @param <T> value
     * @return value
     */
    public static <E, T> T get(E e, Map<E, T> map) {

        return get(e, map, null);
    }


    /**
     * 将bean对象转化为map
     *
     * @param bean bean
     * @param <T>  泛型参数
     * @return map
     */
    public static <T> Map<String, Object> bean2Map(T bean) {
        Map<String, Object> result = new HashMap<>();
        BeanWrapper wrapper = new BeanWrapperImpl(bean);
        for (PropertyDescriptor pd : wrapper.getPropertyDescriptors()) {
            String name = pd.getName();
            if ("class".equals(name)) {
                continue;
            }
            Object value = wrapper.getPropertyValue(name);
            result.put(name, value);
        }
        return result;
    }

    /**
     * 将bean对象转化为map
     *
     * @param beans beans
     * @param <T>   泛型参数
     * @return list
     */
    public static <T> List<Map<String, Object>> bean2Map(List<T> beans) {
        return beans.stream().map(MapUtils::bean2Map).toList();
    }

    /**
     * 将map对对象转为bean
     *
     * @param map       map
     * @param beanClass bean
     * @param <T>       泛型参数
     * @return bean
     */
    public static <T> T map2Bean(Map<String, Object> map, Class<T> beanClass) {
        T bean;
        try {
            bean = beanClass.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        BeanWrapper wrapper = new BeanWrapperImpl(bean);
        map.forEach((key, value) -> {
            if (value != null) {
                wrapper.setPropertyValue(key, value);
            }
        });
        return bean;
    }

    /**
     * @param maps      maps
     * @param beanClass bean
     * @param <T>       泛型参数
     * @return list
     */
    public static <T> List<T> map2Bean(List<Map<String, Object>> maps, Class<T> beanClass) {
        return maps.stream().map(map -> map2Bean(map, beanClass)).toList();
    }

    /**
     * @param map       map
     * @param beanClass 转换的对象
     * @param <T>       对象泛型
     * @return 对象
     */
    public static <T> T underscoreToCamelCase(Map<String, Object> map, Class<T> beanClass) {
        Map<String, Object> objectMap = new HashMap<>();
        map.forEach((k, v) -> objectMap.put(CharacterUtils.underscoreToCamelCase(k), v));
        return map2Bean(objectMap, beanClass);
    }

}
